from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.conf import settings
import random
from django_redis import get_redis_connection
from users.models import UserModel
import re
from users.serializers import CustomTokenObtainPairSerializer


class loginSmsViews(APIView):

    def post(self, request):
        mobile = request.data.get('mobile', None)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({'message': '手机号格式错误'}, status=status.HTTP_400_BAD_REQUEST)

        sms_code = request.data.get('sms_code')
        redis = get_redis_connection('sms_code')
        # 获取的都是字节类型
        code = redis.get(f'loginSms_{mobile}')
        if code is None:
            return Response({'message': '验证码已过期，请重新发送！'}, status=status.HTTP_400_BAD_REQUEST)
        elif code.decode() != sms_code:
            return Response({'message': '验证码错误，请重试！'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            redis.delete(f'loginSms_{mobile}')

        # 程序健壮性考虑
        # 判断一次用户是否存在
        try:
            user = UserModel.objects.get(mobile__exact=mobile)
            refresh = CustomTokenObtainPairSerializer.get_token(user)
            data = {
                'refresh': str(refresh),
                'token': str(refresh.access_token)
            }
            # user.refresh = str(refresh)
            # user.token = str(refresh.access_token)
            return Response({'message': '登录成功', 'data': data}, status=status.HTTP_200_OK)
        except UserModel.DoesNotExist:
            user = UserModel.objects.create_user(
                mobile=mobile,
                password='123456',
                username=mobile,
                avatar='avatar/2024/default.jpg'
            )
            refresh = CustomTokenObtainPairSerializer.get_token(user)
            data = {
                'refresh': str(refresh),
                'token': str(refresh.access_token)
            }
            return Response({'message': '登录成功', 'data': data}, status=status.HTTP_200_OK)


# 手机号唯一注册
class MobileViews(APIView):
    def get(self, request, mobile):
        try:
            UserModel.objects.get(mobile__exact=mobile)
            return Response({'message': '手机号已存在，请登录或修改密码！'}, status=status.HTTP_400_BAD_REQUEST)
        except UserModel.DoesNotExist:
            return Response({'message': '手机号允许注册！'}, status=status.HTTP_200_OK)


class LoginSmsApiView(APIView):

    def get(self, request, mobile):
        # -------------------redis:短信验证码------------------
        redis = get_redis_connection('sms_code')
        res_interval = redis.ttl(f'loginSms_{mobile}')
        if res_interval != -2:
            return Response({'message': '验证码还在有效期内,请勿频繁发送验证码', 'interval': res_interval}, status=status.HTTP_400_BAD_REQUEST)
        # -------------------redis:短信验证码------------------

        # 获取容联云配置信息
        rly = settings.RONG_LIAN_YUN
        # 获取短信模板
        tid = rly.get('reg_tid')
        sms_expire = rly.get('sms_expire')
        # 获取发送间隔
        sms_interval = rly.get('sms_interval')

        # mobile = '18201275696'
        # 生成验证码，格式化操作，不足4位，前面补0
        code = f'{random.randint(0, 9999):04d}'
        # 配置文件中秒位单位，容联云以分钟位单位
        interval = sms_interval / 60
        # 基本发送短信完成
        # 如何存储验证码
        # 生成发送短信的datas
        datas = (code, interval)
        # tid = "1"
        # mobile = '18201275696'
        # datas = ('9823', '2')
        # 调用发送验证码函数
        # res = send_message(tid, mobile, datas)
        from mycelery.sms.tasks import send_sms
        send_sms.delay(tid, mobile, datas)

        # -------------------redis:短信验证码------------------
        # redis写入验证码,     sms_18201275699
        # redis  提供了  简单事务
        # 开启管道,优化redis写入, 执行的,一次性将所有指令发送给redis
        # 开启事务
        pipe = redis.pipeline()
        pipe.multi() # 开启redis事务,保证所有命令 正确执行
        redis.setex(f'loginSms_{mobile}', sms_expire, code)
        # 短信发送的间隔时间
        redis.setex(f'loginInterval_{mobile}', sms_interval, '-')
        # 提交事务,把暂存在pipeline对象中多条命令,一次性提交给redis
        pipe.execute()
        # -------------------redis:短信验证码------------------

        # if res:
        return Response({'message': '短信发送成功...'}, status=status.HTTP_200_OK)
        # else:
        #     return Response({'message': '短信发送失败...'}, status=status.HTTP_400_BAD_REQUEST)


class RegisterSmsApiView(APIView):

    def get(self, request, mobile):
        # -------------------redis:短信验证码------------------
        redis = get_redis_connection('sms_code')
        res_interval = redis.ttl(f'registerSms_{mobile}')
        if res_interval != -2:
            return Response({'message': '验证码还在有效期内,请勿频繁发送验证码', 'interval': res_interval}, status=status.HTTP_400_BAD_REQUEST)
        # -------------------redis:短信验证码------------------

        # 获取容联云配置信息
        rly = settings.RONG_LIAN_YUN
        # 获取短信模板
        tid = rly.get('reg_tid')
        sms_expire = rly.get('sms_expire')
        # 获取发送间隔
        sms_interval = rly.get('sms_interval')

        # mobile = '18201275696'
        # 生成验证码，格式化操作，不足4位，前面补0
        code = f'{random.randint(0, 9999):04d}'
        # 配置文件中秒位单位，容联云以分钟位单位
        interval = sms_interval / 60
        # 基本发送短信完成
        # 如何存储验证码
        # 生成发送短信的datas
        datas = (code, interval)
        from mycelery.sms.tasks import send_sms
        send_sms.delay(tid, mobile, datas)

        # -------------------redis:短信验证码------------------
        # redis写入验证码,     sms_18201275699
        # redis  提供了  简单事务
        # 开启管道,优化redis写入, 执行的,一次性将所有指令发送给redis
        # 开启事务
        pipe = redis.pipeline()
        pipe.multi() # 开启redis事务,保证所有命令 正确执行
        redis.setex(f'registerSms_{mobile}', sms_expire, code)
        # 短信发送的间隔时间
        redis.setex(f'registerInterval_{mobile}', sms_interval, '-')
        # 提交事务,把暂存在pipeline对象中多条命令,一次性提交给redis
        pipe.execute()
        # -------------------redis:短信验证码------------------

        return Response({'message': '短信发送成功...'}, status=status.HTTP_200_OK)


class RegisterViews(APIView):

    def post(self, request):
        mobile = request.data.get('mobile', None)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({'message': '手机号格式错误'}, status=status.HTTP_400_BAD_REQUEST)
        password = request.data.get('password', None)
        print(password)
        if len(password) < 8 or len(password) > 16:
            return Response({'message': '密码长度必须在8到16位之间'}, status=status.HTTP_400_BAD_REQUEST)
        if not re.match(r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z\d]).+$', password):
            return Response({'message': '密码必须包含字母、数字和特殊字符'}, status=status.HTTP_400_BAD_REQUEST)

        sms_code = request.data.get('sms_code')
        redis = get_redis_connection('sms_code')
        # 获取的都是字节类型
        code = redis.get(f'registerSms_{mobile}')
        if code is None:
            return Response({'message': '验证码已过期，请重新发送！'}, status=status.HTTP_400_BAD_REQUEST)
        elif code.decode() != sms_code:
            return Response({'message': '验证码错误，请重试！'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            redis.delete(f'registerSms_{mobile}')
        user = UserModel.objects.create_user(
            mobile=mobile,
            password=password,
            username=mobile,
            avatar='avatar/2024/default.jpg'
        )
        refresh = CustomTokenObtainPairSerializer.get_token(user)
        data = {
            'refresh': str(refresh),
            'token': str(refresh.access_token)
        }
        return Response({'message': '注册成功', 'data': data}, status=status.HTTP_200_OK)


# 找回密码容联云短信发送
class ForgetPwdSmsApiView(APIView):

    def get(self, request, mobile):
        # -------------------redis:短信验证码------------------
        redis = get_redis_connection('sms_code')
        res_interval = redis.ttl(f'forgetPwdSms_{mobile}')
        if res_interval != -2:
            return Response({'message': '验证码还在有效期内,请勿频繁发送验证码', 'interval': res_interval}, status=status.HTTP_400_BAD_REQUEST)
        # -------------------redis:短信验证码------------------

        # 获取容联云配置信息
        rly = settings.RONG_LIAN_YUN
        # 获取短信模板
        tid = rly.get('reg_tid')
        sms_expire = rly.get('sms_expire')
        # 获取发送间隔
        sms_interval = rly.get('sms_interval')

        # mobile = '18201275696'
        # 生成验证码，格式化操作，不足4位，前面补0
        code = f'{random.randint(0, 9999):04d}'
        # 配置文件中秒位单位，容联云以分钟位单位
        interval = sms_interval / 60
        # 基本发送短信完成
        # 如何存储验证码
        # 生成发送短信的datas
        datas = (code, interval)
        from mycelery.sms.tasks import send_sms
        send_sms.delay(tid, mobile, datas)

        # -------------------redis:短信验证码------------------
        # redis写入验证码,     sms_18201275699
        # redis  提供了  简单事务
        # 开启管道,优化redis写入, 执行的,一次性将所有指令发送给redis
        # 开启事务
        pipe = redis.pipeline()
        pipe.multi() # 开启redis事务,保证所有命令 正确执行
        redis.setex(f'forgetPwdSms_{mobile}', sms_expire, code)
        # 短信发送的间隔时间
        redis.setex(f'forgetPwdInterval_{mobile}', sms_interval, '-')
        # 提交事务,把暂存在pipeline对象中多条命令,一次性提交给redis
        pipe.execute()
        # -------------------redis:短信验证码------------------

        return Response({'message': '短信发送成功...'}, status=status.HTTP_200_OK)


class ForgetPwdView(APIView):

    def post(self, request):
        """
        找回密码逻辑处理，校验找回密码的手机号是否存在以及验证码是否正确
        """
        mobile = request.data.get('mobile', None)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({'message': '手机号格式错误'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            user = UserModel.objects.get(mobile__exact=mobile)
            if user:
                sms_code = request.data.get('sms_code')
                redis = get_redis_connection('sms_code')
                # 获取的都是字节类型
                code = redis.get(f'forgetPwdSms_{mobile}')
                if code is None:
                    return Response({'message': '验证码已过期，请重新发送！'}, status=status.HTTP_400_BAD_REQUEST)
                elif code.decode() != sms_code:
                    return Response({'message': '验证码错误，请重试！'}, status=status.HTTP_400_BAD_REQUEST)
                else:
                    redis.delete(f'forgetPwdSms_{mobile}')
                return Response({'message': '找回校验成功'}, status=status.HTTP_200_OK)
        except UserModel.DoesNotExist:
            return Response({'message': '找回校验失败，手机号不存在，请直接登录或注册！'}, status=status.HTTP_400_BAD_REQUEST)




class ResetPwdViews(APIView):

    def post(self, request):
        """
        重置密码逻辑处理
        """
        mobile = request.data.get('mobile', None)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({'message': '手机号格式错误'}, status=status.HTTP_400_BAD_REQUEST)
        password = request.data.get('password')
        re_password = request.data.get('re_password')
        if password != re_password:
            return Response({'message': '两次密码不一致,请重新输入密码'}, status=status.HTTP_400_BAD_REQUEST)
        if len(password) < 8 or len(password) > 16:
            return Response({'message': '密码长度必须在8到16位之间'}, status=status.HTTP_400_BAD_REQUEST)
        if not re.match(r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z\d]).+$', password):
            return Response({'message': '密码必须包含字母、数字和特殊字符'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            user = UserModel.objects.get(mobile__exact=mobile)
            if user:
                user.set_password(password)
                user.save()
                return Response({'message': '重置密码成功'}, status=status.HTTP_200_OK)
        except UserModel.DoesNotExist:
            return Response({'message': '重置密码失败，手机号不存在，请直接登录或注册！'}, status=status.HTTP_400_BAD_REQUEST)